package main

import (
	"database/sql"
	"encoding/json"
	"log"
	"net/http"
	"strconv"
	"time"

	"github.com/gorilla/mux"
	_ "github.com/lib/pq"
	"gorm.io/driver/postgres"
	"gorm.io/gorm"
)

// 数据模型
type Task struct {
	ID        uint           `json:"id" gorm:"primaryKey"`
	Title     string         `json:"title"`
	Completed bool           `json:"completed"`
	CreatedAt time.Time      `json:"created_at"`
	UpdatedAt time.Time      `json:"updated_at"`
	DeletedAt gorm.DeletedAt `json:"-" gorm:"index"`
}

var db *gorm.DB

// 初始化数据库连接
func initDB() {
	// 使用与测试程序相同的成功连接字符串
	connStr := "host=localhost port=5432 user=postgres password=5616616 dbname=postgres sslmode=disable"

	log.Println("尝试连接到数据库...")
	log.Printf("连接字符串: %s\n\n", connStr)

	// 方法1: 先使用标准库建立连接，然后传递给GORM
	sqlDB, err := sql.Open("postgres", connStr)
	if err != nil {
		log.Fatalf("无法使用标准库打开数据库连接: %v\n", err)
	}

	// 测试标准库连接
	err = sqlDB.Ping()
	if err != nil {
		log.Fatalf("标准库连接测试失败: %v\n", err)
	}
	log.Println("标准库连接成功!")

	// 将已有的sql.DB连接传递给GORM
	db, err = gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{})
	if err != nil {
		log.Printf("\n=== 详细错误信息 ===\n")
		log.Printf("错误类型: %T\n", err)
		log.Printf("错误内容: %v\n\n", err)
		log.Fatalf("Failed to connect to database with GORM\n")
	}

	log.Println("GORM成功连接到数据库!")

	// 检查数据库中是否存在与 Task 结构体对应的表，没有就创建，有就同步
	db.AutoMigrate(&Task{})
}

// 中间件：日志记录
func loggingMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		log.Printf("%s %s %s", r.RemoteAddr, r.Method, r.URL)
		next.ServeHTTP(w, r)
	})
}

// 中间件：设置JSON响应头
func jsonMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		w.Header().Set("Content-Type", "application/json")
		next.ServeHTTP(w, r)
	})
}

// 处理函数：获取所有任务
func getTasks(w http.ResponseWriter, r *http.Request) {
	var tasks []Task
	db.Find(&tasks)
	json.NewEncoder(w).Encode(tasks)
}

// 处理函数：获取单个任务
func getTask(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{"error": "无效的ID"})
		return
	}

	var task Task
	result := db.First(&task, id)
	if result.Error != nil {
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(map[string]string{"error": "任务不存在"})
		return
	}

	json.NewEncoder(w).Encode(task)
}

// 处理函数：创建任务
func createTask(w http.ResponseWriter, r *http.Request) {
	var task Task
	_ = json.NewDecoder(r.Body).Decode(&task)

	task.Completed = false
	task.CreatedAt = time.Now()
	task.UpdatedAt = time.Now()

	result := db.Create(&task)
	if result.Error != nil {
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{"error": "创建任务失败"})
		return
	}

	w.WriteHeader(http.StatusCreated)
	json.NewEncoder(w).Encode(task)
}

// 处理函数：更新任务
func updateTask(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{"error": "无效的ID"})
		return
	}

	var task Task
	result := db.First(&task, id)
	if result.Error != nil {
		w.WriteHeader(http.StatusNotFound)
		json.NewEncoder(w).Encode(map[string]string{"error": "任务不存在"})
		return
	}

	var updatedTask Task
	_ = json.NewDecoder(r.Body).Decode(&updatedTask)

	task.Title = updatedTask.Title
	task.Completed = updatedTask.Completed
	task.UpdatedAt = time.Now()

	db.Save(&task)
	json.NewEncoder(w).Encode(task)
}

// 处理函数：删除任务
func deleteTask(w http.ResponseWriter, r *http.Request) {
	params := mux.Vars(r)
	id, err := strconv.Atoi(params["id"])
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		json.NewEncoder(w).Encode(map[string]string{"error": "无效的ID"})
		return
	}

	result := db.Delete(&Task{}, id)
	if result.Error != nil {
		w.WriteHeader(http.StatusInternalServerError)
		json.NewEncoder(w).Encode(map[string]string{"error": "删除任务失败"})
		return
	}

	w.WriteHeader(http.StatusNoContent)
}

func main() {
	// 初始化数据库
	initDB()
	defer func() {
		sqlDB, _ := db.DB()
		sqlDB.Close()
	}()

	// 创建路由器
	r := mux.NewRouter()

	// 应用中间件
	r.Use(loggingMiddleware)
	r.Use(jsonMiddleware)

	// 定义路由
	r.HandleFunc("/tasks", getTasks).Methods("GET")
	r.HandleFunc("/tasks/{id:[0-9]+}", getTask).Methods("GET")
	r.HandleFunc("/tasks", createTask).Methods("POST")
	r.HandleFunc("/tasks/{id:[0-9]+}", updateTask).Methods("PUT")
	r.HandleFunc("/tasks/{id:[0-9]+}", deleteTask).Methods("DELETE")

	// 启动服务器
	log.Println("Server starting on port 8181...")
	log.Fatal(http.ListenAndServe(":8181", r))
}
